#include "GfxD3D9.h"

using namespace imGraphics;

D3D9Shader::D3D9Shader() {
	m_Fx = NULL;
}

D3D9Shader::~D3D9Shader() {
	if(m_Fx != NULL) {
		m_Fx->Release();
		m_Fx = NULL;
	}
}

void D3D9Shader::LoadShader(char* Path) {
	LPD3DXBUFFER code = NULL; //Temporary buffer
	HRESULT hr = S_OK;

	hr = D3DXCreateEffectFromFile(	g_DeviceD3D9,
									Path,
									0, // Macros
									0,
									D3DXSHADER_DEBUG,//D3DXSHADER_DEBUG
									0,
									&m_Fx,
									&code);

	if(FAILED(hr)) {
		/* If there's a problem compiling the effect, show a message box showing why! */
		char* scode = (char*)code->GetBufferPointer();
		char buffer[1000];

		_snprintf_s(buffer, 1000, "Error in effect code!\n'%s'", scode);
		MessageBox(NULL, buffer, "Imagine - Error", MB_OK | MB_ICONERROR);
			
		code->Release();

		m_Fx = NULL;
	}
}

void D3D9Shader::SetDiffuse(const Vector4 &Diffuse) {
	D3DXHANDLE hDiffuse = m_Fx->GetParameterByName(0, "gDiffuse");
	m_Fx->SetVector(hDiffuse, &D3DXVECTOR4(Diffuse.x, Diffuse.y, Diffuse.z, Diffuse.w));
}

void D3D9Shader::SetSpecular(const Vector4 &Specular) {
	D3DXHANDLE hSpecular = m_Fx->GetParameterByName(0, "gSpecular");
	m_Fx->SetVector(hSpecular, &D3DXVECTOR4(Specular.x, Specular.y, Specular.z, Specular.w));
}

void D3D9Shader::SetSrcBlend(const BlendAlpha &SrcBlend) {
}

void D3D9Shader::SetDestBlend(const BlendAlpha &DestBlend) {
}

void D3D9Shader::SetWireframe(const bool &Wireframe) {
	if(Wireframe)
		g_DeviceD3D9->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	else
		g_DeviceD3D9->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
}

void D3D9Shader::SetCullMode(const CullMode &Mode) {
}

void D3D9Shader::FillMatrices() {
	if(m_Fx == NULL) return;

	D3DXHANDLE hWorld = m_Fx->GetParameterByName(0, "gWorld");
	D3DXHANDLE hWVP = m_Fx->GetParameterByName(0, "gWVP");
	D3DXHANDLE hWIT = m_Fx->GetParameterByName(0, "gWIT");

	D3DXMATRIX WVP, WIT;
	D3DXMatrixMultiply(&WVP, g_World, g_VP);

	D3DXMatrixInverse(&WIT, 0, (const D3DXMATRIX*)g_World);
	D3DXMatrixTranspose(&WIT, &WIT);
		
	m_Fx->SetMatrix(hWorld, (const D3DXMATRIX*)g_World);
	m_Fx->SetMatrix(hWVP, &WVP);
	m_Fx->SetMatrix(hWIT, &WIT);

	m_Fx->CommitChanges();
}

void D3D9Shader::StartRender() {
	if(m_Fx == NULL) return;

	// Set up textures
	D3DXHANDLE hDiffuse = m_Fx->GetParameterByName(0, "gDiffuseTex");
	D3DXHANDLE hSpecular = m_Fx->GetParameterByName(0, "gSpecularTex");
	D3DXHANDLE hNormal = m_Fx->GetParameterByName(0, "gNormalTex");
	m_Fx->SetTexture(hDiffuse, g_Tex[TEX_DIFFUSE]);
	m_Fx->SetTexture(hSpecular, g_Tex[TEX_SPECULAR]);
	m_Fx->SetTexture(hNormal, g_Tex[TEX_NORMAL]);

	// Begin rendering using the main technique
	D3DXHANDLE hTech = m_Fx->GetTechniqueByName("DiffuseTech");
	m_Fx->SetTechnique(hTech);
	m_Fx->Begin(0, 0);
	m_Fx->BeginPass(0);
}

void D3D9Shader::EndRender() {
	if(m_Fx == NULL) return;

	m_Fx->EndPass();
	m_Fx->End();
}